package com.gaul.util;

import com.gaul.action.Action;
import com.gaul.annotation.Controller;
import com.gaul.annotation.Resource;
import org.dom4j.Document;
import org.dom4j.Element;
import org.dom4j.io.SAXReader;

import java.io.File;
import java.io.InputStream;
import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * 初始化时，解析xml配置，获取扫描路径
 */
public class XmlParser {
	public static Map<String, Action> parseXml(InputStream xmlName) {
		System.out.println("parsing xml...");
		Map<String, Action> resultMap = new HashMap<String, Action>();
		try{
			SAXReader reader = new SAXReader();
			Document doc = reader.read(xmlName);
			
			//获取根元素
			Element rootElement = doc.getRootElement();
//			System.out.println(rootElement.getName());
			
			//获取扫描路径
			Element scan = rootElement.element("component-scan");
			String scanPackage = scan.attribute("base-package").getValue();
			
			String classpath = Thread.currentThread().getContextClassLoader().getResource("/").getPath();
			
			//获得所有扫描路径
			String[] scanPaths = scanPackage.split(",");
			
			String packagePath;
			File file;
			List<Class> classes = new ArrayList<Class>();
			for(String scanPath : scanPaths) {
				packagePath = classpath + scanPath.replace(".", "/");
				file = new File(packagePath);

				System.out.println("scanning package: " + packagePath);
				
				iterateFile(file, classpath, classes);
			}

			System.out.println("getting annotation value, total " + classes.size() + " class");

			//遍历每一个Class，获取注解
			Controller controller = null;
			Resource resource = null;
			String classValue = null;
			String methodValue = null;
			for(Class c : classes) {
				//获取class上的注解值
				if(c.isAnnotationPresent(Controller.class)) {
					controller = (Controller) c.getAnnotation(Controller.class);
					classValue = controller.value();
				}

				//获取method上的注解值
				Method method = c.getMethod("execute", new Class[]{});
				if(method.isAnnotationPresent(Resource.class)) {
					resource = method.getAnnotation(Resource.class);
					methodValue = resource.value();
				}
				System.out.println("xmlParser:"+classValue+methodValue);
				resultMap.put(classValue + methodValue, (Action) c.newInstance());
			}
		} catch (Exception e){
			e.printStackTrace();
			throw new RuntimeException(e);
		}
		return resultMap;
	}

	private static void iterateFile(File file, String classPath, List<Class> classes) {
		String filePath;
		Class clazz = null;
		try{
			if(file.isDirectory()) {
				File[] files = file.listFiles();
				for(File f : files){
					iterateFile(f, classPath, classes);
				}
			} else {
				filePath = file.getAbsolutePath();
				filePath = filePath.replace("\\", ".").replace("/", ".");
				filePath = filePath.split(".classes.")[1].split(".class")[0];

				clazz = Class.forName(filePath);

				System.out.println("file path: " + filePath);
				classes.add(clazz);
			}
		} catch (Exception e){
			e.printStackTrace();
			throw new RuntimeException(e);
		}
	}
}
